package com.fjnldx.mes.utils;

import com.fjnldx.mes.domain.domainRes.DataSummary;
import com.fjnldx.mes.domain.domainRes.GxGroupData;
import com.fjnldx.mes.domain.domainRes.SumLuoTong;
import com.fjnldx.mes.domain.enums.CurrentDh;
import com.fjnldx.mes.domain.enums.WeekEnum;
import com.fjnldx.mes.domain.pojo.SperoTable;
import com.fjnldx.mes.mapper.productionFigures.ProductionFiguresMapper;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Stream;

@Component
public class Common {
    @Resource
    RedisUtils redisUtils;

    @Autowired
    ProductionFiguresMapper productionFiguresMapper;

    private final Logger logger = LoggerFactory.getLogger(Common.class);

    /**
     * 判断参数是否在枚举类中
     *
     * @param data
     * @return
     */
    public boolean judgeEnumIsExist(String data) {
        boolean is_exist = false;
        //遍历枚举类
        for (CurrentDh u : CurrentDh.values()) {
            if (u.getValue().equals(data)) {
                is_exist = true;
                break;
            }
        }
        return is_exist;
    }

    /**
     * 校验表是否存在
     *
     * @param tableName
     * @return
     */
    public boolean checkTableIsExits(String tableName) {
        Integer haveTable = productionFiguresMapper.isHaveDataByXs(tableName);
        return haveTable != 0;
    }

    /**
     * 获取一段时间的每一天日期
     */
    public List<LocalDate> getBetweenDate(LocalDate startDate, LocalDate endDate) {
        List<LocalDate> list = new ArrayList<>();
        long distance = ChronoUnit.DAYS.between(startDate, endDate);
        if (distance < 1) {
            return list;
        }
        Stream.iterate(startDate, d -> d.plusDays(1)).limit(distance + 1).forEach(list::add);
        return list;
    }

    /**
     * 获取一段时间中的每一天
     *
     * @param dBegin
     * @param dEnd
     * @return
     */
    public List<Date> findDates(Date dBegin, Date dEnd) {
        List<Date> lDate = new ArrayList<>();
        lDate.add(dBegin);
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(calBegin.getTime());
        }
        return lDate;
    }

    public List<LocalDate> findLocalDateBetween(LocalDate dBegin, LocalDate dEnd) {
        List<LocalDate> lDate = new ArrayList<>();
        long between = ChronoUnit.DAYS.between(dBegin, dEnd)+1;
        logger.info("【天数（LocalDateBetween）：】{}；", between);
        for (int i = 0; i < between; i++) {
            lDate.add(dBegin);
            dBegin = dBegin.plusDays(1);
        }
        return lDate;
    }

    /**
     * 查看周三数量
     */
    public Integer getWednesdayNum(List<LocalDate> dateBetween) {
        int num = 0;
        for (LocalDate d : dateBetween) {
            if (WeekEnum.Wednesday.getVal().equals(String.valueOf(d.getDayOfWeek()))) {
                num++;
            }
        }
        return num;
    }

    /**
     * 处理头尾所需班次数
     */

    public Integer getBcNum(LocalDateTime startTime, LocalDateTime endTime) {
        int num = 0;

        LocalDateTime timeNode0 = getTimeNode(startTime.toLocalDate(), 0);
        LocalDateTime timeNode8 = getTimeNode(startTime.toLocalDate(), 8);
        LocalDateTime timeNode12 = getTimeNode(startTime.toLocalDate(), 12);
        LocalDateTime timeNode16 = getTimeNode(startTime.toLocalDate(), 16);
        LocalDateTime timeNode24 = getTimeNode(startTime.toLocalDate(), 24);

        // startTime：周三
        if (WeekEnum.Wednesday.getVal().equals(String.valueOf(startTime.getDayOfWeek()))) {
            // x<8
            if (Duration.between(startTime, timeNode8).toMillis() / 1000 > 0) {
                logger.info("【x<8】");
                num = num + 3;
            }
            // 8<x<16
            else if (Duration.between(startTime, timeNode16).toMillis() / 1000 > 0) {
                logger.info("【8<x<16】");
                num = num + 2;
            }
            // 16<x<24
            else if (Duration.between(startTime, timeNode0).toMillis() / 1000 != 0 && Duration.between(startTime, timeNode24).toMillis() / 1000 > 0) {
                logger.info("【8<x<16】");
                num = num + 1;
            }
        } else {
            // startTime：非周三
            // 0<x<12
            if (Duration.between(startTime, timeNode12).toMillis() / 1000 > 0) {
                logger.info("【x<12】");
                num = num + 2;
            }
            // 12<x<24
            else if (Duration.between(startTime, timeNode0).toMillis() / 1000 != 0 && Duration.between(startTime, timeNode24).toMillis() / 1000 > 0) {
                logger.info("【12<x<24】");
                num = num + 1;
            }
        }
        // endTime：周三
        if (WeekEnum.Wednesday.getVal().equals(String.valueOf(startTime.getDayOfWeek()))) {
            // 0<x<8
            if (Duration.between(endTime, timeNode0).toMillis() / 1000 != 0 && Duration.between(endTime, timeNode8).toMillis() / 1000 > 0) {
                logger.info("【x<8】");
                num = num + 1;
            }
            // 8<x<16
            else if (Duration.between(endTime, timeNode16).toMillis() / 1000 > 0) {
                logger.info("【8<x<16】");
                num = num + 2;
            }
            // 16<x<24
            else if (Duration.between(endTime, timeNode24).toMillis() / 1000 > 0) {
                logger.info("【8<x<16】");
                num = num + 3;
            }
        } else {
            // endTime：非周三
            // x<12
            if (Duration.between(endTime, timeNode0).toMillis() / 1000 != 0 && Duration.between(endTime, timeNode12).toMillis() / 1000 > 0) {
                logger.info("【x<12】");
                num = num + 1;
            }
            // 12<x<24
            else if (Duration.between(endTime, timeNode24).toMillis() / 1000 > 0) {
                logger.info("【12<x<24】");
                num = num + 2;
            }
        }
        return num;
    }

    public LocalDateTime getTimeNode(LocalDate time, Integer hour) {
        LocalDateTime timeNode = null;
        switch (hour) {
            case 0:
                timeNode = LocalDateTime.of(time, LocalTime.of(0, 0, 0));
                break;
            case 8:
                timeNode = LocalDateTime.of(time, LocalTime.of(8, 0, 0));
                break;
            case 12:
                timeNode = LocalDateTime.of(time, LocalTime.of(12, 0, 0));
                break;
            case 16:
                timeNode = LocalDateTime.of(time, LocalTime.of(16, 0, 0));
                break;
            case 24:
                timeNode = LocalDateTime.of(time, LocalTime.of(23, 59, 59));
                break;
            default:
        }
        return timeNode;
    }
    //==========================

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    public boolean isExistKey(String key) {
        Jedis jedis = redisUtils.Jedis();
        String s = jedis.get(key);
        return s != null;
    }

    /**
     * 设置key存活时间
     *
     * @param key
     * @param value
     * @param seconds
     * @return
     */
    public String setKeyLifeTime(String key, String value, Integer seconds) {
        Jedis jedis = redisUtils.Jedis();
        return jedis.setex(key, seconds, value);
    }

    /**
     * time转seconds
     *
     * @param date
     * @return
     */
    public int getSeconds(Date date) {
        Date dateNow = new Date();
        int date1 = dateNow.getDate();
        int hours = dateNow.getHours();
        int minutes = dateNow.getMinutes();
        int seconds = dateNow.getSeconds();
        int date2 = date.getDate();
        return 60 * 60 * 24 - (hours * 60 * 60 + minutes * 60 + seconds) + (date2 - date1) * 60 * 60 * 24;
    }

    /**
     * Date格式化
     */
    public String formatDate(Date date) {
        DateFormat dateInstance = DateFormat.getDateInstance();
        return dateInstance.format(date);
    }

    /**
     * 获取两个时间点之间, 按照整点每隔半小时的字符串类型的时间点
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    public List<String> getPointInTimes(LocalDateTime beginTime, LocalDateTime endTime) {
        return this.getPointInTimesByFormat(beginTime, endTime, "yyyyMMddHHmm");
    }

    public List<String> getDaysBySection(LocalDateTime beginTime, LocalDateTime endTime) {
        return this.getDaysBySectionAndFormat(beginTime, endTime, "yyyyMMdd");
    }

    public List<String> getDaysBySectionAndFormat(LocalDateTime beginTime, LocalDateTime endTime, String format) {
        List<String> daysBySection = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        while (beginTime.compareTo(endTime) != 1) {
            String beginTimeStr = formatter.format(beginTime);
            daysBySection.add(beginTimeStr);
            beginTime = beginTime.plusDays(1);
        }
        return daysBySection;
    }

    public List<String> getDaysBySectionAndFormat(LocalDate beginTime, LocalDate endTime, String format) {
        List<String> daysBySection = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        while (beginTime.compareTo(endTime) != 1) {
            String beginTimeStr = formatter.format(beginTime);
            daysBySection.add(beginTimeStr);
            beginTime = beginTime.plusDays(1);
        }
        return daysBySection;
    }

    /**
     * 获取两个时间点之间, 按照整点每隔半小时的字符串类型的时间点
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    public List<String> getPointInTimesByFormat(LocalDateTime beginTime, LocalDateTime endTime, String format) {
        // 获取开始时间的分钟, 如果大于30分, 则时+1,分归0; 如果小于30分, 则分设置成30;
        Integer beginMinute = beginTime.getMinute();
        if (beginMinute < 30 && beginMinute != 0) {
            beginTime = beginTime.plusMinutes(30 - beginMinute);
        } else if (beginMinute > 30) {
            beginTime = beginTime.plusHours(1);
            beginTime = beginTime.minusMinutes(beginMinute);
        }
        // 获取结束时间的分钟, 如果大于30分, 则按照30分; 如果小于30分, 则按照整点
        Integer endMinute = endTime.getMinute();
        if (endMinute > 30) {
            endTime = endTime.minusMinutes(endMinute - 30);
        } else if (endMinute < 30) {
            endTime = endTime.minusMinutes(endMinute);
        }
        // 定义日期格式化格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        List<String> pointInTimes = new ArrayList<>();
        while (beginTime.compareTo(endTime) != 1) {
            pointInTimes.add(formatter.format(beginTime));
            beginTime = beginTime.plusMinutes(30);
            System.out.println(beginTime.compareTo(endTime));
        }
        return pointInTimes;
    }

    /**
     * 获取今日0点至现在所有的整点时间字符串
     *
     * @return
     */
    public List<String> getHoursNowByToday() {
        LocalDateTime now = LocalDateTime.now();
        List<String> hoursList = new ArrayList<>();
        LocalDateTime zeroDate = LocalDateTime.of(LocalDateTime.now().toLocalDate(), LocalTime.MIN);
        // 定义日期格式化格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
        // 获取现在的小时
        Integer hour = now.getHour();
        while (zeroDate.getHour() <= hour) {
            String zeroDateString = formatter.format(zeroDate);
            hoursList.add(zeroDateString);
            zeroDate = zeroDate.plusHours(1);
        }
        return hoursList;
    }

    public String getTodayStr() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDateTime today = LocalDateTime.now();
        return formatter.format(today);
    }

    /**
     * 字符串日期类型转换
     *
     * @param oldDate   被转换的日期字符串
     * @param oldFormat 被转换的日期字符串格式
     * @param format    要转换成的日期字符串格式
     * @return
     */
    public String dateTimeFormat(String oldDate, String oldFormat, String format) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        LocalDateTime formatLocalDate = LocalDateTime.parse(oldDate, DateTimeFormatter.ofPattern(oldFormat));
        return dateTimeFormatter.format(formatLocalDate);
    }

    // Excel发送响应流方法
    public void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            try {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 数据补全
     *
     * @param start
     * @param end
     * @param list
     * @return
     */
    public List<GxGroupData> completeData(Integer start, Integer end, List<GxGroupData> list) {
        List<GxGroupData> result = new ArrayList<>(list);
        for (int i = start; i <= end; i++) {
            boolean flag = false;
            for (GxGroupData item : list) {
                if (item.getDevSn().equals(String.valueOf(i))) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                GxGroupData xiSha1 = new GxGroupData();
                xiSha1.setDevSn(String.valueOf(i));
                xiSha1.setStateCode("5");
                xiSha1.setXiaolv("0");
                xiSha1.setTime("no time");
                result.add(xiSha1);
            }
        }
        return result;
    }

    //数据排序
    public void sortData(List<GxGroupData> list) {
        list.sort(Comparator.comparingInt(o -> Integer.parseInt(o.getDevSn())));
    }

    /**
     * 汇总数据公共方法
     */
    public DataSummary huiZongLuoTong(SperoTable speroTable) throws JSONException {
        DataSummary luoTongHuiZong = new DataSummary();
        SumLuoTong cx = this.huiZongLuoTongSum(speroTable.getCx(), "cx");
        SumLuoTong mj = this.huiZongLuoTongSum(speroTable.getMj(), "mj");
        SumLuoTong dc = this.huiZongLuoTongSum(speroTable.getDc(), "dc");
        SumLuoTong nj = this.huiZongLuoTongSum(speroTable.getNj(), "nj");
        SumLuoTong xh = this.huiZongLuoTongSum(speroTable.getXh(), "xh");
        SumLuoTong qc = this.huiZongLuoTongSum(speroTable.getQc(), "qc");
        SumLuoTong yj = this.huiZongLuoTongSum(speroTable.getYj(), "yj");
        SumLuoTong hg = this.huiZongLuoTongSum(speroTable.getHg(), "hg");
        SumLuoTong cz = this.huiZongLuoTongSum(speroTable.getCz(), "cz");
        SumLuoTong xtq = this.huiZongLuoTongSum(speroTable.getXq(), "xq");
        SumLuoTong yx = this.huiZongLuoTongSum(speroTable.getYx(), "yx");
        SumLuoTong mt = this.huiZongLuoTongSum(speroTable.getMt(), "mt");
        SumLuoTong cc = this.huiZongLuoTongSum(speroTable.getCc(), "cc");
        SumLuoTong bc = this.huiZongLuoTongSum(speroTable.getBc(), "bc");
        double xl = this.huiZongLuoTongAverage(speroTable.getXl(), "xl");
        luoTongHuiZong.setCx(cx);
        luoTongHuiZong.setMj(mj);
        luoTongHuiZong.setDc(dc);
        luoTongHuiZong.setNj(nj);
        luoTongHuiZong.setXh(xh);
        luoTongHuiZong.setQc(qc);
        luoTongHuiZong.setYj(yj);
        luoTongHuiZong.setHg(hg);
        luoTongHuiZong.setCz(cz);
        luoTongHuiZong.setXtq(xtq);
        luoTongHuiZong.setYx(yx);
        luoTongHuiZong.setMt(mt);
        luoTongHuiZong.setCc(cc);
        luoTongHuiZong.setBc(bc);
        luoTongHuiZong.setXl(xl);
        return luoTongHuiZong;
    }

    /**
     * 汇总数据公共方法--求和
     */
    public SumLuoTong huiZongLuoTongSum(String json, String base) throws JSONException {
        JSONObject jsonObject = new JSONObject(json); // 字符串转object
        int sum1 = 0;
        int sum2 = 0;
        int sum3 = 0;
        int sum4 = 0;
        for (int i = 1; i <= jsonObject.length(); i++) {
            String fBase = base + i;
            if (i <= 16) {
                sum1 += Integer.parseInt(jsonObject.get(fBase).toString());
            } else if (i <= 32) {
                sum2 += Integer.parseInt(jsonObject.get(fBase).toString());
            } else if (i <= 48) {
                sum3 += Integer.parseInt(jsonObject.get(fBase).toString());
            } else if (i <= 64) {
                sum4 += Integer.parseInt(jsonObject.get(fBase).toString());
            }
        }
        SumLuoTong sumLuoTong = new SumLuoTong();
        sumLuoTong.setSum1(sum1);
        sumLuoTong.setSum2(sum2);
        sumLuoTong.setSum3(sum3);
        sumLuoTong.setSum4(sum4);
        return sumLuoTong;
    }

    /**
     * 汇总数据公共方法--求平均
     */
    public double huiZongLuoTongAverage(String json, String base) throws JSONException {
        JSONObject jsonObject = new JSONObject(json); // 字符串转object
        double sum = 0.0;
        for (int i = 1; i <= jsonObject.length(); i++) {
            String fBase = base + i;
            sum += Double.parseDouble(jsonObject.get(fBase).toString());
        }
        return sum / jsonObject.length();
    }

    public String getTodayTableNameByPrefix(String tablePrefix) {
        switch (tablePrefix) {
            case "history_xs_":
                return "xsmzl_table";
            case "history_cs_":
                return "txcsoml_table";
            case "history_cs2_":
                return "txcsomlnew_table";
            case "history_zmj_":
                return "zmj_table";
            case "history_lt_":
                return "spero_table";
            case "history_sma_":
                return "shumianjia_table";
            case "history_sm_":
                return "shumianji_table";
            case "history_kmj_":
                return "jingkaimianji_table";
            default:
                return null;
        }
    }
}
